﻿module core.hgeall;

public import core.hge;
public import core.hgeclass;
public import core.hgerect;
public import core.hgesprite;
//public import hgefont;		// 屏蔽了字体类而启用了CN字体
public import core.hgecnfont2;	
public import core.fontconst;
public import core.hgecnfont;
public import core.hgedistort;
public import core.hgecolor;
public import core.hgevector;
public import core.hgeparticle;
public import core.hgeanim;
public import core.hgegui_bak;
public import core.hgeguictrls;
public	import core.hgescene;


private import	std.c.windows.windows;	//MessageBoxA
private import	std.string;				//toStringz
private import 	std.windows.charset;		//toMBSz

private import    std.utf,
					std.format,
					std.stdarg; 

void msgbox(char[] msg,char[] title ="Message"){
	MessageBoxA(null, toMBSz(msg), toMBSz(title), MB_OK | MB_ICONERROR | MB_APPLMODAL);
}


alias	std.stdio.writefln		mesn;

char[] formatString(TypeInfo[] arguments, va_list argptr) 	// 格式化字符串
{
   char[] message = null; 
   
   void putc(dchar c)
   {
      std.utf.encode(message, c); 
   }
   
   std.format.doFormat(&putc, arguments, argptr);
   
   return message; 
} 


void mes(...){
	gameInfo.hge.System_Log(toMBSz(formatString(_arguments, _argptr)));
}

char[]	tmpLog;			//初始化之前不能输出LOG,所以用这个变量先暂存
	
void mesTmp(...){
	
	tmpLog ~= formatString(_arguments, _argptr);
}

public class	gameInfo{
static	private this()	
		{	phge	= hgeCreate(HGE_VERSION);	//HGE接口只在本类创建时调用一次,在退出时释放一次
			if(phge){
				mesTmp("************************************		HGE类接口已 [获取成功] !\n");
			
			}
			this.res= new myRes(phge);
		}

	private  static   gameInfo   instance ;   
    
    public   static   gameInfo   getInstance()   {   
							if(instance is null){
								instance=new gameInfo ;
							}
							return instance ;  
						}
	public	 static 	uint width(){return  winW;}
	public	 static 	uint height(){return  winH;}
	
	public   static   ifHge   hge()   
								{ 
									if(phge){	
									cont++;	
									//mesTmp("hge 接口被导出!  次数 == ",cont);	
									return phge;	
									}
									else { 
											throw new Exception("执行此方法前必须先创建[ Chge ]对象\n");
									}	
								}			
	
	~this()	{	
				mes("******		程序准备结束 ... ...");
				hgeFontCN.releaseAll();				//释放所有载入的字体
				mes("	*[开始卸载资源] ... ...");	delete res;
				mes("	*[退出程序    ] ... ...");		
				if(phge) 
				{	
					mes("************************************		HGE类接口已 [释放    ]!\n");
					this.end();
					phge.Release();
					phge = 	null;
				}
			}
	void setVideo(int w, int h, int bp =32, bool isWin =true){
		phge.System_SetStateBool( hgeBoolState.HGE_WINDOWED, 	isWin);
		phge.System_SetStateInt( hgeIntState.HGE_SCREENWIDTH, 	w);
		phge.System_SetStateInt( hgeIntState.HGE_SCREENHEIGHT, 	h);
		phge.System_SetStateInt( hgeIntState.HGE_SCREENBPP, 		bp);

		winW=w;
		winH=h;
	}

	void setFunc(hgeCallback  frameFunc,		hgeCallback  renderFunc){
		phge.System_SetStateFunc( hgeFuncState.HGE_FRAMEFUNC, 	frameFunc);
		phge.System_SetStateFunc( hgeFuncState.HGE_RENDERFUNC,	renderFunc);
	}

	void setStr(char[] title, char[] logname){
		phge.System_SetStateString( hgeStringState.HGE_LOGFILE, 	toStringz(logname));
		phge.System_SetStateString( hgeStringState.HGE_TITLE, 	toMBSz(title));
	}
	void fps(uint fp){
		phge.System_SetStateInt( hgeIntState.HGE_FPS, 	fp);
	}
	uint fps( ){
		return 	phge.System_GetStateInt( hgeIntState.HGE_FPS );
	}

	void init()
	{
		if(!phge.System_Initiate()) {
				throw new Exception("	* System_Initiate(); 调用失败!");	
			}
		else
			phge.System_Log(toMBSz(tmpLog));
	}

	
	void run(hgeSceneObj	 sc){
		hgeSceneObj.setScene(sc);
		sc.entry();
		setFunc(&hgeSceneObj.updateAll,&hgeSceneObj.drawAll);
		hge.System_Start();
		hgeSceneObj.releaseAll();
		
	}
		
		
	void end() {			phge.System_Shutdown();	}
		
		static	myRes	res;
		static	uint	winW;
		static	uint 	winH;
	private:
		extern(C) {
			//bool frameFunc(){		};
			//bool drawFunc(){		};
		}
		static	ifHge	phge;
		static uint	cont;
		
}



class	myRes{
	this(ifHge arg){
		phge= arg;
	}
	
	~this(){
		 foreach(t,s; texIndex){	//T=纹理,S=文件名
			
			if(t){
				
				mes("	*卸载纹理!		名称 = ",s);
				
				phge.Texture_Free(t);	//释放所有 纹理资源
				nameIndex.remove(texIndex[t]);
				texIndex.remove(t);	
			}
		} 
	}


	HTEXTURE	tex_load(char[] filename,	uint colorKey=0, uint size=0, bool bMipmap=false)
	{
		if(filename in nameIndex) 	
			return nameIndex[filename];
			
		HTEXTURE tex= phge.Texture_Load(toMBSz(filename), size, bMipmap);
		if(tex){
			mes("	*载入纹理成功!		名称 = ",filename);
			nameIndex[filename] = tex;	texIndex[tex]= filename;		//将刚载入的文件名加入数组中
			
		}else{
			throw new resException(filename);
		}
		if(colorKey){				///////////		****	对纹理进行透空处理
			uint* ptex=	phge.Texture_Lock(tex,false);		//取得纹理图像地址
			uint th=	phge.Texture_GetHeight(tex);		//取纹理宽
			uint tw=	phge.Texture_GetWidth(tex);			//取纹理高
			uint[] sstex= ptex[0..tw*th];					//将指针转换为有限数组,更安全

			uint tmpcolor= colorKey << 8;
			for(int ii=0;ii<tw*th;ii++){
				 if(sstex[ii]<<8 == tmpcolor) 	sstex[ii] &= 0x00FFFFFF;	//如果是关键色,将ALPHA位清零
			 }
				
			phge.Texture_Unlock(tex);						//***解锁图像
			delete		sstex;
			delete		ptex;
		}
		return	 tex;
	}
	
	HTEXTURE	tex_creat(int width, int height, char[] name=null)
	{
		static uint creat_tex_num; 
		
			HTEXTURE tex= phge.Texture_Create(width,height);
			if(tex){
				creat_tex_num++;	//从1开始
				if(name==null) name=	"默认纹理号_" ~ std.string.toString(creat_tex_num);
				mes("	*创建空纹理成功!		名称 = ",name);
				nameIndex[name] = tex;	texIndex[tex]= name;		//将刚载入的文件名加入数组中
				
			}else{
				throw new resException(name);
			}
	}
	void		tex_free(HTEXTURE tex)
	{
		if(tex in texIndex){
			mes("	*卸载纹理!		名称 = ",texIndex[tex]);
			nameIndex.remove(texIndex[tex]);	//删除文件名数组
			texIndex.remove(tex);					//删除纹理数组键值
			phge.Texture_Free(tex);	//卸载纹理
		}
	}


	private:
	static	ifHge 					phge= null;

	static	HTEXTURE[char[]]  		nameIndex;		//纹理数组,以文件名索引
	static char[][HTEXTURE]		texIndex;		//文件名数组,以纹理号为索引

} 

class resException :Exception
{
	 this(char[] msg)
    {
		super("	*载入纹理失败!		名称 = " ~ msg);
    }
} 

class hgeException : Exception
{
	/// Just wraps the Exception constructor.
	this(char[] msg)
	{
		super(" HGE 异常信息:	"~msg);
	}
}